/*
 *所有关于MaterialRequisition类的业务代码应在此处编写
*可使用repository.调用常用方法，获取EF/Dapper等信息
*如果需要事务请使用repository.DbContextBeginTransaction
*也可使用DBServerProvider.手动获取数据库相关信息
*用户信息、权限、角色等使用UserContext.Current操作
*MaterialRequisitionService对增、删、改查、导入、导出、审核业务代码扩展参照ServiceFunFilter
*/
using Mercury.Core.BaseProvider;
using Mercury.Core.Extensions.AutofacManager;
using Mercury.Entity.DomainModels;
using System.Linq;
using Mercury.Core.Utilities;
using System.Linq.Expressions;
using Mercury.Core.Extensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http;
using Mercury.Order.IRepositories;
using System.Collections.Generic;
using System.Threading.Tasks;
using System;
using Mercury.Core.Enums;

namespace Mercury.Order.Services
{
    public partial class MaterialRequisitionService
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IMaterialRequisitionRepository _repository;//访问数据库

        [ActivatorUtilitiesConstructor]
        public MaterialRequisitionService(
            IMaterialRequisitionRepository dbRepository,
            IHttpContextAccessor httpContextAccessor
            )
        : base(dbRepository)
        {
            _httpContextAccessor = httpContextAccessor;
            _repository = dbRepository;
            //多租户会用到这init代码，其他情况可以不用
            //base.Init(dbRepository);
            DelOnExecuting =(keys) =>
            {
                if (keys == null || !keys.Any())
                    return Response.Error("删除异常！");
                var bill = _repository.FindFirst(c => keys.Select(x => x.ToString()).Contains(c.Id) && c.State == 5);
                if (bill != null) 
                {
                    return Response.Error($"计划领料单【{bill.BatchingNo}】已确认，不能删除！");
                }
                return Response.OK();
            };
        }


        protected override IEnumerable<Detail> JoinTableByBeforeQuery<Detail>(IQueryable<Detail> join)
        {
            var temp = join as IQueryable<MaterialRequisitionDetailed>;
            var queryable = repository.DbContext.Set<MaterialMaster>().Where(c => c.DeletionFlag == 0 || !c.DeletionFlag.HasValue);


            var list = from d in temp
                       join m in queryable
          on d.MaterialId equals m.Id into DD
                       from dc in DD.DefaultIfEmpty()
                       select new MaterialRequisitionDetailed
                       {
                           Catefory = !dc.Category.HasValue ? 2 : dc.Category.Value,
                           MaterialId = d.MaterialId,
                           Id = d.Id,
                           BatchNumber = d.BatchNumber,
                           DeliveryWeight = d.DeliveryWeight,
                           MaterialName = d.MaterialName,
                           MRId = d.MRId,
                           Notes = d.Notes,
                           RequiredWeight = d.RequiredWeight
                       };

            //var list = temp.Join(queryable, d => d.MaterialId, m => m.Id, (d, m) => new MaterialRequisitionDetailed
            //{
            //    Catefory = m.Category,
            //    MaterialId = d.MaterialId,
            //    Id = d.Id,
            //    BatchNumber = d.BatchNumber,
            //    DeliveryWeight = d.DeliveryWeight,
            //    MaterialName = d.MaterialName,
            //    MRId = d.MRId,
            //    Notes = d.Notes,
            //    RequiredWeight = d.RequiredWeight
            //});
            return list as IEnumerable<Detail>;
        }

        public async Task<bool> EditStatus(string id)
        {
            var bill = await repository.FindFirstAsync(c => c.Id == id);
            if (bill != null)
            {
                bill.State = 1;
                var type = typeof(MaterialRequisition);
                var list = new List<string>();
                list.Add("State");
                list.AddRange(type.ModifyFields());
                bill.SetModifyDefaultVal();
                return repository.Update(bill, list.ToArray(), true) > 0;
            }
            return true;
        }


        public async Task<WebResponseContent> CreateStoresRequisition(List<string> orderNos)
        {
            if (!orderNos.Any()) return Response.Error("请选择需要生成清单的领料单！");


            var tempList = (from d in _repository.DbContext.Set<MaterialRequisitionDetailed>().Where(c => orderNos.Contains(c.MRId)).ToList()
                            join m in _repository.DbContext.Set<MaterialRequisition>()
                            on d.MRId equals m.Id
                            into dd
                            from dc in dd
                            select new { d.MaterialId, d.MaterialName, d.RequiredWeight, dc.OrderNumber, dc.State, d.BatchNumber }).ToList();

            var computedBill = tempList.FirstOrDefault(c => c.State == 5);
            if (computedBill != null) return Response.Error($"计划单{computedBill.OrderNumber}已生成领料清单，请勿重复操作！");

            var order = tempList.Select(c => c.OrderNumber).Distinct().ToList();

            var groupData = tempList.GroupBy(c => new { c.MaterialId, c.MaterialName, c.BatchNumber }).Select(c => new
            {
                c.Key.MaterialId,
                c.Key.MaterialName,
                RequiredWeight = c.Sum(c => c.RequiredWeight.GetDouble()),
                c.Key.BatchNumber

            });

            var count = await _repository.DbContext.Set<StoresRequisition>().CountAsync(c => c.CreateDate >= DateTime.Now.Date);
            var billId = Guid.NewGuid().ToString();
            var bill = new StoresRequisition()
            {
                Id = billId,
                DeletionFlag = 0,
                SRNumber = $"SR{DateTime.Now.ToString("yyyyMMdd")}{count.ToString().PadLeft(6, '0')}"
            };
            bill.SetCreateDefaultVal();
            var billDetail = groupData.Select(c =>
            {
                var model = new StoresRequisitionDetailed()
                {
                    Id = Guid.NewGuid().ToString(),
                    SRId = billId,
                    MaterialId = c.MaterialId,
                    MaterialName = c.MaterialName,
                    Notes = "自动生成",
                    RequiredWeight = c.RequiredWeight.ToDecimal(),
                    DeliveryWeight = 0,
                    BatchNumber = c.BatchNumber
                };
                model.SetCreateDefaultVal();
                return model;
            }).ToList();

            var list = order.Select(c => new StoresRequisitionOrder()
            {
                SRId = billId,
                OrderNumber = c
            }).ToList();
            Response = _repository.DbContextBeginTransaction(() =>
            {
                orderNos.ForEach(c =>
                {
                    var model = new MaterialRequisition() { Id = c, State = 5 };
                    model.SetModifyDefaultVal();
                    _repository.Update(model, x => new { x.State });
                });
                _repository.DbContext.Entry(bill).State = EntityState.Added;
                billDetail.ForEach(e =>
                {
                    _repository.DbContext.Entry(e).State = EntityState.Added;
                });
                list.ForEach(c =>
                {
                    _repository.DbContext.Entry(c).State = EntityState.Added;
                });
                repository.DbContext.SaveChanges();
                Response.OK("生成领料清单成功！请前往领料清单查看!");
                return Response;
            });

            return Response;
        }

    }
}
